chore: production deploy - #6416
Conversation
supabase-cli-releaser
Bot
commented
Sep 1, 2026
- feat(cli): add supabase workers new (feat(cli): add supabase workers new #6261)
- feat(cli): add supabase workers push (feat(cli): add supabase workers push #6262)
- chore(deps): bump the go-minor group across 2 directories with 1 update (chore(deps): bump the go-minor group across 2 directories with 1 update #6350)
- chore: sync API types from infrastructure (chore: sync API types from infrastructure #6352)
- feat(stack): replace remote runtime protocol with Effect RPC (feat(stack): replace remote runtime protocol with Effect RPC #6303)
- chore(repo): remove Nx (chore(repo): remove Nx #6344)
- chore(api): sync Management API OpenAPI spec (chore(api): sync Management API OpenAPI spec #6338)
- fix(docker): bump the docker-minor group across 1 directory with 5 updates (fix(docker): bump the docker-minor group across 1 directory with 5 updates #6320)
- chore(api): sync Management API OpenAPI spec (chore(api): sync Management API OpenAPI spec #6356)
- chore: sync API types from infrastructure (chore: sync API types from infrastructure #6359)
- chore(release): harden release-notes prompt against injection (chore(release): harden release-notes prompt against injection #6361)
- feat(config): add toProjectConfig and the ProjectConfig hosted subset (CLI-2230) (feat(config): add toProjectConfig and the ProjectConfig hosted subset (CLI-2230) #6339)
- ci(repo): add one-shot two-model AI review pipeline (ci(repo): add one-shot two-model AI review pipeline #6358)
- ci(repo): fix ai-review gh repo inference and scripts-ci timeout (ci(repo): fix ai-review gh repo inference and scripts-ci timeout #6363)
- feat(cli): add supabase workers list, status and delete (feat(cli): add supabase workers list, status and delete #6263)
- chore(lint): scope Effect checks to stack packages (chore(lint): scope Effect checks to stack packages #6357)
- chore: sync API types from infrastructure (chore: sync API types from infrastructure #6373)
- ci(repo): parallel AI review passes with a Codex adjudicator, no size cap (ci(repo): parallel AI review passes with a Codex adjudicator, no size cap #6365)
- ci(repo): fix codex-action v1.12 hang (downgrade to v1.11), adjudicate on >=1 review (ci(repo): fix codex-action v1.12 hang (downgrade to v1.11), adjudicate on >=1 review #6380)
- fix(stack): prepare slim postgres socket directory (fix(stack): prepare slim postgres socket directory #6401)
- chore: sync API types from infrastructure (chore: sync API types from infrastructure #6399)
- test(stack): qualify complete slim Docker service graph (test(stack): qualify complete slim Docker service graph #6374)
- fix(cli): accept sbp_v0 tokens (CLI-2262) (fix(cli): accept sbp_v0 tokens (CLI-2262) #6360)
- test(stack): qualify native Postgres, Auth, and PostgREST core (test(stack): qualify native Postgres, Auth, and PostgREST core #6379)
- fix(cli): stop skipping colliding schemas (CLI-2272) (fix(cli): stop skipping colliding schemas (CLI-2272) #6394)
- docs(repo): add public-surfaces rule to agent instructions (docs(repo): add public-surfaces rule to agent instructions #6400)
- test(cli): cover services and storage mv (test(cli): cover services and storage mv #6362)
- test(cli): cover migration up and repair (CLI-2269) (test(cli): cover migration up and repair (CLI-2269) #6376)
- chore: sync API types from infrastructure (chore: sync API types from infrastructure #6402)
- feat(cli): add SUPABASE_USE_SLIM_IMAGES flag for slim ghcr images (feat(cli): add SUPABASE_USE_SLIM_IMAGES flag for slim ghcr images #6382)
- docs(cli): document SUPABASE_USE_SLIM_IMAGES side effects (docs(cli): document SUPABASE_USE_SLIM_IMAGES side effects #6383)
- perf(cli): strategy-driven parallel provisioning for pg-delta next plan shadows (perf(cli): strategy-driven parallel provisioning for pg-delta next plan shadows #6215)
- chore: bump postgres-meta to v0.99.0 (chore: bump postgres-meta to v0.99.0 #6405)
- chore(api): sync Management API OpenAPI spec (chore(api): sync Management API OpenAPI spec #6377)
- feat(cli): make shadow baseline cache opt-out (default ON) (feat(cli): make shadow baseline cache opt-out (default ON) #6403)
- test(stack): derive image assertions from the service catalog (test(stack): derive image assertions from the service catalog #6406)
- feat(cli): move workers commands under experimental parent (feat(cli): move workers commands under experimental parent #6409)
- fix(deps): bump github.com/posthog/posthog-go from 1.23.1 to 1.24.0 in /apps/cli-go in the go-minor group across 1 directory (fix(deps): bump github.com/posthog/posthog-go from 1.23.1 to 1.24.0 in /apps/cli-go in the go-minor group across 1 directory #6412)
## Summary Adds `supabase workers new`, plus the project layout and `config.toml` editing the whole command family builds on: - `shared/workers/` — worker path resolution, `config.toml` section reading and patching (`toml-section.ts` preserves surrounding formatting), the runtime/size envelope, and the starter files. - Starter files live as ordinary files under `shared/workers/stacks/<runtime>/` rather than string literals, and are embedded into the compiled binary through a Bun macro — the directory is expanded at transpile time and inlined. A completeness check inside the macro fails the build if `WORKER_RUNTIMES` and the directory drift apart. **Stack 2 of 4**, on top of the config schema (#6260). Reviewer note: the third commit is where the embedding mechanism is explained; the starters are deliberately kept out of the type program (a `deno` starter is not valid under this workspace's Bun types), which is why `tsconfig.json` excludes the directory and nothing imports the files. ## Linked issue FUNC-753 (Linear). Supabase maintainer, exempt from the `open-for-contribution` flow. ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/) --------- Co-authored-by: Kanad Gupta <git@kanad.dev>
## Summary Adds `supabase workers push` (aliased `deploy`) and the machinery it needs: - `workers-api.ts` — the typed Workers Management API client. - `tar.ts` / `worker-package.ts` — packaging a worker directory into the build context that gets uploaded. - `worker-classify.ts` — best-effort runtime detection from marker files, so a directory with no `[workers.<name>] runtime` can still deploy. The guess is always reported with a nudge to pin it down, never applied silently. **Stack 3 of 4**, on top of `workers new` (#6261). ## Linked issue FUNC-753 (Linear). Supabase maintainer, exempt from the `open-for-contribution` flow. ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/)
…te (#6350) Bumps the go-minor group with 1 update in the /apps/cli-go directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go). Bumps the go-minor group with 1 update in the /apps/cli-go/pkg directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go). Updates `google.golang.org/grpc` from 1.83.0 to 1.83.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p> <blockquote> <h2>Release 1.83.1</h2> <h1>Security</h1> <ul> <li>xds/rbac: Fix a bug where nested <code>Principal</code> or <code>Permission</code> rules with <code>:scheme</code> or <code>grpc-</code> prefixed header matchers were not rejected, which could cause DENY rules to fail open. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>) <ul> <li>Special Thanks: <a href="https://github.com/nvxbug"><code>@nvxbug</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where the <code>host</code> header matcher was not being replaced with <code>:authority</code> in nested <code>Principal</code> or <code>Permission</code> rules. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>) <ul> <li>Special Thanks: <a href="https://github.com/nvxbug"><code>@nvxbug</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a header matcher whose name was not lowercase, such as <code>X-Role</code>, matched no header, which could cause DENY rules to fail open. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a <code>:scheme</code> or <code>grpc-</code> prefixed header matcher was accepted when its name was not lowercase. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a <code>Host</code> header matcher was not replaced with <code>:authority</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> </ul> <h1>Performance</h1> <ul> <li>transport: Restrict memory overhead of buffering small data frames. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/grpc/grpc-go/commit/1550d9e0cddb30ce99e61a2102e8294a49461e5e"><code>1550d9e</code></a> Change version to 1.83.1 (<a href="https://redirect.github.com/grpc/grpc-go/issues/9336">#9336</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/ebba6f3f1b206e2b4dc4d1d5a96d18430302c2fe"><code>ebba6f3</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a> and <a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a> into v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9335">#9335</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/8cfeca0e1ee5ea0980dcc320e20240fa1079ec77"><code>8cfeca0</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a> to v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9333">#9333</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/dec6951305e88906696f1d0a00dd2439363bc708"><code>dec6951</code></a> Change version to 1.83.1-dev (<a href="https://redirect.github.com/grpc/grpc-go/issues/9229">#9229</a>)</li> <li>See full diff in <a href="https://github.com/grpc/grpc-go/compare/v1.83.0...v1.83.1">compare view</a></li> </ul> </details> <br /> Updates `google.golang.org/grpc` from 1.83.0 to 1.83.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p> <blockquote> <h2>Release 1.83.1</h2> <h1>Security</h1> <ul> <li>xds/rbac: Fix a bug where nested <code>Principal</code> or <code>Permission</code> rules with <code>:scheme</code> or <code>grpc-</code> prefixed header matchers were not rejected, which could cause DENY rules to fail open. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>) <ul> <li>Special Thanks: <a href="https://github.com/nvxbug"><code>@nvxbug</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where the <code>host</code> header matcher was not being replaced with <code>:authority</code> in nested <code>Principal</code> or <code>Permission</code> rules. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>) <ul> <li>Special Thanks: <a href="https://github.com/nvxbug"><code>@nvxbug</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a header matcher whose name was not lowercase, such as <code>X-Role</code>, matched no header, which could cause DENY rules to fail open. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a <code>:scheme</code> or <code>grpc-</code> prefixed header matcher was accepted when its name was not lowercase. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a <code>Host</code> header matcher was not replaced with <code>:authority</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> </ul> <h1>Performance</h1> <ul> <li>transport: Restrict memory overhead of buffering small data frames. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/grpc/grpc-go/commit/1550d9e0cddb30ce99e61a2102e8294a49461e5e"><code>1550d9e</code></a> Change version to 1.83.1 (<a href="https://redirect.github.com/grpc/grpc-go/issues/9336">#9336</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/ebba6f3f1b206e2b4dc4d1d5a96d18430302c2fe"><code>ebba6f3</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a> and <a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a> into v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9335">#9335</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/8cfeca0e1ee5ea0980dcc320e20240fa1079ec77"><code>8cfeca0</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a> to v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9333">#9333</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/dec6951305e88906696f1d0a00dd2439363bc708"><code>dec6951</code></a> Change version to 1.83.1-dev (<a href="https://redirect.github.com/grpc/grpc-go/issues/9229">#9229</a>)</li> <li>See full diff in <a href="https://github.com/grpc/grpc-go/compare/v1.83.0...v1.83.1">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
## Summary - Replace the runtime REST and SSE daemon protocol with a static control plane exposing owner discovery, session-fenced shutdown, and same-version Effect RPC over HTTP and NDJSON. - Use the immutable, unique CLI version as the sole runtime compatibility identity; source execution uses the explicit 0.0.0-dev development sentinel. - Make an incompatible CLI version an explicit parent-owned full stack stop/start authorized only by supabase start; connect-only and ordinary child paths report the typed upgrade requirement without restarting the live owner. - Preserve managed data, document and launch metadata, runtime selection, pinned service versions, raw exclusions, and sticky ports across the upgrade restart. - Serialize startup, runtime scope ownership, terminal persistence, and shutdown through one Effect Queue-backed SupervisorSession actor, releasing the control listener last across Node, Bun, and compiled Bun runtimes. - Update CLI consumers, error reporting, integration helpers, targeted process coverage, and durable architecture documentation for the single-protocol cutover. ## Linked issue None. ## Reviewer context This intentionally has no legacy protocol window, compatibility adapter, adoption path, or in-place supervisor swap. Runtime RPC is a same-version boundary; owner discovery and session-fenced shutdown remain the stable cross-build protocol. Upgrading through supabase start restarts the complete stack, so active application connections and tooling streams disconnect briefly while durable state and launch selections remain intact.
## Summary - remove the remaining Nx configuration, package metadata, inference plugin workspace, dependencies, cache ignores, and lockfile graph - update current contributor guidance to use package scripts and root-owned Turbo tasks for execution and dependency inspection - preserve the build, generation, quality, live, auxiliary, and test graphs established by the preceding Turborepo migrations ## Context PR #6343 merged while this change was in progress, so this branch was rebased onto the updated `develop` branch containing its final live and auxiliary task migration. Task execution is now owned entirely by package scripts and Turbo. Affected execution, persistent cache storage, and remote caching remain separate follow-up optimizations.
This PR was automatically created to sync the generated `@supabase/api` package with the latest Management API OpenAPI document. Changes were detected in the upstream OpenAPI documents exposed by `https://api.supabase.com/api/v1-json` and `https://api.supabase.com/api/v2-json`. Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com>
…dates (#6320) Bumps the docker-minor group with 5 updates in the /apps/cli-go/pkg/config/templates directory: | Package | From | To | | --- | --- | --- | | postgrest/postgrest | `v16.1` | `v16.2` | | supabase/studio | `2026.08.17-sha-0c1da8f` | `2026.08.24-sha-8ec45b2` | | supabase/realtime | `v2.129.3` | `v2.129.9` | | supabase/storage-api | `v1.70.3` | `v1.71.0` | | supabase/logflare | `1.50.4` | `1.50.6` | Updates `postgrest/postgrest` from v16.1 to v16.2 Updates `supabase/studio` from 2026.08.17-sha-0c1da8f to 2026.08.24-sha-8ec45b2 Updates `supabase/realtime` from v2.129.3 to v2.129.9 Updates `supabase/storage-api` from v1.70.3 to v1.71.0 Updates `supabase/logflare` from 1.50.4 to 1.50.6 Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Julien Goux <hi@jgoux.dev>
This PR was automatically created to sync the generated `@supabase/api` package with the latest Management API OpenAPI document. Changes were detected in the upstream OpenAPI documents exposed by `https://api.supabase.com/api/v1-json` and `https://api.supabase.com/api/v2-json`. Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com>
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
## Summary
Defense-in-depth hardening for the automated release-notes generator
(`propose-release-notes.yml` →
`apps/cli/scripts/propose-release-notes.ts`), which runs the Claude
Agent SDK with `Bash` + `WebFetch`/`WebSearch` and feeds it the
semantic-release changelog block (built from contributor commit subjects
/ PR titles) plus PR bodies and linked issues it fetches at runtime —
all attacker-influenceable content, previously with no injection guard.
This PR adds an explicit **trust boundary** to
`tools/release/release-notes-prompt.md`:
- A top-of-file section establishing that the changelog block and all
fetched PR/issue/web content are **untrusted data to be summarized,
never instructions to obey**.
- Rules that override embedded instructions: don't act on injected
commands; never disclose env vars / secrets / tokens; restrict `Bash` to
read-only `gh` GETs on `supabase/cli`; restrict `WebFetch`/`WebSearch`
to `github.com/supabase/cli`; produce only the release-notes markdown.
- Inline reminders at the two points where untrusted content enters (the
changelog block and the PR-investigation step).
The `{{PASTE_SEMANTIC_RELEASE_BLOCK_HERE}}` placeholder is unchanged, so
the generator's template check and output contract are unaffected.
## Scope / follow-up
This is **defense-in-depth only** — prompt guards are best-effort
against a determined injection. The stronger, structural containment is
deliberately **left for a follow-up**:
1. Separate the write-capable GitHub App token (`GH_TOKEN`,
`contents`/`pull-requests: write` on the protected default branch) from
the agent's process — generate notes in an agent-only step with no GH
token, then push/open the PR in a separate step that runs no model.
2. Drop `Bash` (and ideally `WebFetch`) from the agent's `allowedTools`,
pre-fetching the PR/issue data with trusted code instead — removing the
shell/network exfiltration primitive.
Context: surfaced during the security review of the AI-review pipeline
(#6358); the release-notes workflow shares the "untrusted content +
secrets in an agentic CI job" class of exposure, gated behind a
maintainer-cut stable release rather than per-PR.
… (CLI-2230) (#6339) ## What changed Implements [CLI-2230](https://linear.app/supabase/issue/CLI-2230/create-a-toprojectconfig-function-that-is-exported-from-the-config): the hosted-project subset type `ProjectConfig` and its normalizers, exported from `@supabase/config`'s pure (browser-safe) entrypoint so the CLI and Studio share one mapper. - **`fromConfigDocument(config)`** — projection of a `CliConfig` document (or any `EffectiveConfig`) down to the hosted sections (`api`, `auth`, `db`, `realtime`, `storage`, `workers`, `experimental`). - **`fromApiProjectConfig(input)`** — translation of a Management API v2 project-config response (full envelope, `data` object, or bare `data.attributes`). Registry-driven: 233 mapping rows mined from the legacy `config push` sync mappers (`config-sync/*.sync.ts`), covering renames (`rate_limit_otp` → `sign_in_sign_ups`), boolean inversions (`disable_signup`, `mailer_autoconfirm`), unit conversions (seconds/hours → Go duration strings, int64 bytes → BytesSize), the GoTrue key table (19 OAuth providers, 6 hooks, 5 SMS providers), and `x-secret` omission (the API only reports HMAC digests). Decode is lenient per ADR 0019 — unknown/API-ahead keys never fail; the raw attributes ride along as a **non-enumerable `_apiResponse`** (invisible to encodes, spreads, and structural walks; never persisted), with a registry-derived `unmappedApiFields()` reader. - **`toProjectConfig(source)`** — thin dispatcher over both (`{ cliConfig }` / `{ apiResponse }`). ### Operand widening (ruling on CLI-2230) `ProjectConfig` is deliberately **sparse** — an API response never mentions sections it doesn't manage, and flooding in schema defaults would fabricate drift. To make it a first-class operand of the comparison core, `BaseCliConfig` is replaced by the family-neutral `EffectiveConfig = DeepPartial<Omit<CliConfig, "remotes">>` on `subtractCliConfig`/`omitDefaultValues`. No runtime change — the subtraction walk already had the right absence semantics. Recorded in ADR 0018's 2026-08-26 addendum; the naming-rule generalization lands separately with CLI-2238 (#6335). ### apps/cli - A type-drift guard (`project-config-api-drift.unit.test.ts`) pins the generated `V2GetProjectConfigOutput` attributes against the package's lenient input schema: assignability (catches type widening) plus per-section key-set assertions (catch added/removed/renamed fields) — so OpenAPI drift fails compile before it can silently break the mapping. No runtime dependency on `packages/api` was added. - `ProjectConfigParseError` registered in the error-actionability table as `apiStatus` (a malformed platform response, not a user config mistake). ### Reviewer notes - Deliberate divergences from the legacy apply semantics are documented inline where they occur: API `null` → omit (sparse output has no local document to fall back to), `uri_allow_list` trimming, `smtp_host: ""` treated as disabled, `sms_autoconfirm` **not** inverted (matches `auth.sync.ts:1677/:2485` — only the mailer counterpart inverts). - An explicit `db_schema: ""` maps to `{ api: { enabled: false } }` only, mirroring `applyRemoteApiConfig`'s early return; an *absent* `db_schema` doesn't gate the sibling fields. - Follow-up candidate deliberately not in this PR: a parity test pinning the replicated legacy helpers (duration/BytesSize/parseUint16/envToMap/password charsets) against their `apps/cli` originals. (ADR 0019's attach helper *did* land in the second round below, as `attachApiResponse`.) ### Second review round (commit 93b4679) — adjudication record A two-set review (architect/engineer/security/DX + adversarial execution) ran against bdd607f. The registry mapping itself survived three independent verification passes with zero defects; every accepted finding about the surrounding surface is fixed in 93b4679: - **Secrets**: `fromConfigDocument` now deep-copies and omits every `x-secret` leaf (schema-derived, `lib/secret-paths.ts`) — decoded documents hold plaintext credentials, and the subtract composition rendered them as drift. - **Spelling convergence**: new registry `normalizeDocument` column canonicalizes document-side duration and byte-size spellings so both normalizers emit one form for one logical value. - **Leniency**: the mirror schema types every never-mapped field `Schema.Unknown`, so a platform type change on a field nothing reads can no longer fail every decode. - **Errors**: `ProjectConfigParseError` gained `message`/`detail`/`suggestion` (upgrade-then-report), schema-issue paths lift into `apiPath`, telemetry adds `fingerprint_suffix: "api_response"` + `has_suggestion`. - **Type-mismatch unification**: string rows, `smtp_host`/`smtp_port`, and CIDR entries now throw typed errors instead of fabricating values (`enabled: false`), vanishing silently, or partially filtering a security allowlist; `expectNumber` rejects non-finite. - **`_apiResponse`**: cloned + deep-frozen at attach (no caller aliasing); `attachApiResponse` export restores it across spread/clone round-trips; invisibility claim narrowed (serializers and walks — debug inspectors like Bun's `console.log` still print it; never log an API-sourced config). - **`unmappedApiFields`**: recursion depth cap; `unmappedSecretApiPaths` deny list (`external_figma_secret` — the one genuine orphan digest; the review's other two candidates don't exist in the legacy source). - **New guards/exports**: `registry-integrity.unit.test.ts` (all 233 rows' paths resolve against the schema ASTs, 470 generated cases); drift-guard key-set levels completed; `comparableProjectConfigPaths`/`isComparableProjectConfigPath` so diff consumers never hand-maintain field lists; `inverse` implementations dropped until the push mapper derives them. **Explicit rejections** (reviewed, not silently deferred): 1. *`alsoConsumes` static consumed-set*: "consumed" means known-to-this-registry-version, not mapped-on-this-run — an `alsoConsumes` sibling whose anchor didn't run stays suppressed by design and remains in `_apiResponse`. Documented in `walkUnmapped`. 2. *WeakMap sidecar for `_apiResponse`*: deferred — clone+freeze resolves the aliasing hazard and the narrowed docstring is honest; revisit if CLI-2156 consumption shows inspectors bite (ADR 0019 records the alternative). 3. *`fromCliConfig`/`fromApiResponse` renaming*: the shipped names are already recorded in ADR 0020 (#6335), Linear, and coordinated docs — symmetry isn't worth re-coordinating three artifacts. 4. *Branding `EffectiveConfig`*: took the ADR 0018 consequence note instead (widening removes the static every-section guarantee; callers own operand completeness). 5. *`ProjectConfigApiAttributes` placement* and *`"sideEffects": false`*: deferred to their owning issues with notes filed — CLI-2234 (export-surface audit) and CLI-2232 (verify the bundler claim against a built artifact). ### Verification round (commits 5f389c9 + 0424ac7) An executed verification pass over 93b4679 re-ran all prior attacks (10/10 now pass) and surfaced residuals, fixed in 0424ac7: - **Orphan digests were 3, not 1** — the generated `V1GetAuthServiceConfigOutput` contract (not the legacy interface) is the authority; `external_slack_secret`, `hook_after_user_created_secrets`, and `nimbus_oauth_client_secret` join the deny list, and a new apps/cli **contract-guard test** cross-checks every auth apiPath + secret-suffixed contract key against the registry (also closing the open-Record vacuity in the integrity test's auth checks). Registry rows are now exported from the package root to serve it. - **Clone/freeze regression fixed**: deep/cyclic/non-cloneable payloads now throw `ProjectConfigParseError` instead of raw `RangeError`/`DOMException` (depth-capped pre-walk, wrapped clone, cycle-guarded `deepFreeze`). - **README example rewritten and executed** (the previous snippet self-subtracted and filtered section names — always empty); secret-stripped projections prune emptied containers; a real phantom-drift pin replaces an agreeing-case test; `comparableProjectConfigPaths`' docstring narrowed to the section-level claim it delivers; ADR 0019 gained a dated addendum (attach helper, structural "verbatim", debug-inspector caveat). - **Documented-not-changed**: byte-size canonicalization quantizes at 4 significant digits symmetrically on both arms — sub-0.1% differences comparing equal is a deliberate property (user-authored spellings are exact). The merge commit resolves the pre-agreed README conflict with #6335 (their `## Naming` section wins, its "in flight" sentence flipped) and de-stales ADR 0020's phrasing, per the coordinated rebase checklist. Known external: root `check:all` fails on `@supabase/cli-go#lint:check` (5 gosec findings in Go files byte-identical to develop — develop-side/toolchain, not this PR). ### Drift-audit round (commit 492ee25) A 2026-08-27 audit compared the post-codex state against CLI-2230's design intent. All eight structural commitments verified intact (pure entrypoint, no `packages/api` dependency, sparse output + `EffectiveConfig`, ADR 0019 guardrails, registry-driven with `inverse` unimplemented, purity graph, naming, secret stripping). Three executed repros surfaced semantic drift introduced by the codex rounds; fixed here: - **Leniency**: `JSON.parse('{"x":1e400}')` yields `Infinity`, so the round-12 non-finite pre-decode rejection hard-failed a real JSON payload on an *unknown* field (mis-bucketed as `caller_misuse`). The walk now rejects only bigint/`undefined`/`NaN` (values `JSON.parse` cannot produce); non-finite values decode and surface as `null` from `unmappedApiFields` (scalars and inside array leaves, identity preserved for all-finite arrays). ADR 0019 gains a dated leniency-boundary addendum. - **SMTP absence semantics**: an absent `smtp_host` previously counted as the disabled sentinel, silently dropping `smtp_user`/`smtp_admin_email`/`rate_limit.email_sent` from both the output and `unmappedApiFields` — contradicting the SMS absent-vs-sentinel rule beside it. Absence now says nothing; only the explicit `""`/`null` legacy sentinel disables (three-state, extended to the `email_sent` cross-section rule). - **Convergence-predictor ruling (ADR 0021)**: the codex rounds had incrementally turned both normalizers into *post-push convergence predictors* (SMS provider precedence flips extra enabled providers, disabled-sentinel pruning, `null`-gated booleans, CSV/uint/duration canonicalization) — defensible (it kills phantom drift for CLI-2156) but never adjudicated or documented. Ruling: **accepted**, now recorded in ADR 0021, the `ProjectConfig`/`fromConfigDocument`/`fromApiProjectConfig` docstrings, and the README ("not a verbatim representation" caveat). - **Guards**: the three hand-written sentinel/precedence tables (`DISABLED_SENTINEL_PRUNES`, `DISABLED_SENTINEL_ENTRY_SWEEPS`, `SMS_PROVIDER_PUSH_PRECEDENCE`) now resolve every path/key against the schema ASTs in `registry-integrity` — previously a schema rename silently no-opped them — and the SMS precedence order is pinned against the legacy push switch (`auth.sync.ts:2498-2539`). - Residual cleanups: the stale `Math.trunc` comment above the fraction arithmetic (round-11/14 artifact the round-20 revert missed), `ReadonlyJsonValue` exported (it appears in public types), `smtpExplicitlyDisabledInAttributes` simplified to mirror `smsProviderExplicitlyUnset`, ADR index gains 0020/0021. An engineer-review pass over the fix diff verified every change; its findings (the `email_sent` asymmetry, stale ADR citations, formatter gate, doc phrasing) are folded in. 984/984 package tests, 461/461 apps/cli guard tests, typechecks clean both packages. Follow-ups filed so they survive CLI-2230 closing: [CLI-2266](https://linear.app/supabase/issue/CLI-2266/derive-the-config-push-mapper-from-the-projectconfig-mapping-registry) (registry-derived push mapper — carries the three requirements previously parked as CLI-2230 comments) and [CLI-2267](https://linear.app/supabase/issue/CLI-2267/pin-supabaseconfigs-replicated-legacy-parsers-with-parity-fixtures-in) (parity fixtures pinning the replicated legacy parsers against `config-sync/*`). Fixes CLI-2230 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
Replaces the Codex GitHub App's per-push auto-review churn (often 30–40
short rounds per PR) with an in-repo pipeline that reviews each PR
**exactly once**, unless a maintainer explicitly re-runs it.
**Pipeline** (`.github/workflows/ai-review.yml`; full design + security
model in `.github/ai-review/README.md`):
1. **resolve** — decides whether to run: once-per-PR dedup (bot-authored
marker), draft/bot/fork skips for auto triggers, `/ai-review`
authorization (requires repo **write/admin** via effective-permission
lookup), diff-size guard. Runs only trusted default-branch code.
2. **claude-review** — Claude Code headless (`claude-fable-5`), one
exhaustive pass, read-only tools, JSON validated against
`findings.schema.json`.
3. **codex-review** — `openai/codex-action` (`gpt-5.6-sol`, drop-sudo +
read-only sandbox): independent review **plus** adjudication of every
Claude finding (confirmed / refuted-with-evidence / uncertain), merged
into `merged-review.schema.json`.
4. **post-review** — deterministic Bun script posts **one** consolidated
PR review (`COMMENT`, advisory only): inline comments for anchorable
findings, refuted findings preserved in a collapsed section (never
silently dropped), verdict counts computed locally (not trusted from the
model). Re-runs supersede the prior review.
**Once-per-PR**: no `synchronize` trigger, bot-authored marker dedup,
per-PR concurrency (non-command comments can't cancel an in-flight run).
Re-run only via `/ai-review` (maintainers) or `workflow_dispatch`.
## Security model
This ran through security + engineering review (twice). A critical
secret-exfiltration path was found and closed; the design now enforces:
- **Model jobs never execute PR-authored code.** The PR head is checked
out only as read-only review subject matter (`claude` reads it with
Read/Grep/Glob under `--bare`/`--strict-mcp-config`); every executed
file — prompts, schemas, the validator script — comes from a separate
trusted default-branch checkout, and no `bun` process ever runs with a
cwd inside the PR checkout (so a PR-authored `bunfig.toml`/`.env` can't
preload code). npm installs are config-isolated and version-pinned;
Codex reviews from `/tmp` with no PR checkout at all.
- **Least privilege**: top-level `permissions: {}`; model jobs hold no
write scope; the only write-capable job (`post-review`) runs base-branch
code exclusively. All actions SHA-pinned.
- **Output is scrubbed**: model-provided text is sanitized
(mentions/refs/HTML neutralized, `file` field guarded against markdown
breakout) and secret-pattern-redacted before it's posted or uploaded as
an artifact (defense-in-depth; a dedicated rotatable key is the real
containment — see README).
- Advisory-only (`COMMENT`), never a required check, never runs in the
merge queue.
## Rollout (shadow mode)
The `pull_request` trigger ships **commented out**. Plan: add a
dedicated `OPENAI_API_KEY` secret (and ideally a dedicated
`ANTHROPIC_API_KEY` rather than the shared release-notes key), tune
prompts against real PRs via `workflow_dispatch`, then enable the
trigger and switch the Codex app to manual-only simultaneously. Steps +
caveats in the README.
## Notes for reviewers
- New `.github/workflows/github-scripts-ci.yml` finally runs the
`.github/scripts` test suites + type-check in CI (they ran nowhere
before — this also covers the pre-existing `contribution-gate` tests).
- Requires a new `OPENAI_API_KEY` repo secret; `ANTHROPIC_API_KEY`
already exists.
Two CI fixes for the AI-review pipeline (#6358), both surfaced immediately after merge. ## 1. `Claude review` job fails at "Fetch PR diff and metadata" The first live `/ai-review` run failed with `fatal: not a git repository`. The `claude-review` job checks out into **subdirectories** (`pr/` for the PR head, `trusted/` for the base), so `$GITHUB_WORKSPACE` itself isn't a git repo — and `gh pr diff`/`gh pr view` infer the repo from the current directory's git remote. Fix: pass `--repo "$GITHUB_REPOSITORY"` explicitly at both `gh` call sites (claude-review and, defensively, codex-review) so `gh` never depends on cwd. ## 2. `Test and type-check` (github-scripts-ci) times out The shared `./.github/actions/setup` installs the full workspace + Go toolchain via mise (~9–10 min), which raced the job's `timeout-minutes: 10` and got cancelled on a cold cache (the setup step never finished; tests/type-check never ran). Raised to 20 min. Noted inline that the check is heavier than it needs to be for two scripts — slimming the setup is a possible follow-up.
## Summary Completes the command family with the three remaining subcommands: - `workers list` — this project's workers. - `workers status` — one worker in detail. - `workers delete` — remove a worker, with confirmation. All three reuse the API client and output helpers introduced in #6262, so this is the smallest layer of the stack. **Stack 4 of 4**, on top of `workers push` (#6262). ## Linked issue FUNC-753 (Linear). Supabase maintainer, exempt from the `open-for-contribution` flow. ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/)
## Summary Set up Effect-aware Oxlint for `packages/stack` and `packages/process-compose` using the Effect-recommended Oxlint preset and TypeScript plugin. The scoped check is wired into the monorepo task graph and denies warnings, matching the global Oxlint policy. The generic pass excludes these two packages while the scoped config extends the generic ruleset, so generic and Effect rules each run exactly once without bringing Effect lint into `apps/cli`. Remediate the existing scoped diagnostics in reviewable waves: typed Effect failures and schema decoding, reusable Effect and Stream service values, lifecycle-safe transport cleanup, and focused test-boundary cleanup. Persisted managed-stack documents and identity markers now encode through the same schemas used to read them. The merged #6303 transport architecture remains authoritative. Exact `apps/cli` callsites were updated where the stack Effect service API changed, but CLI code is intentionally not an Effect-lint target yet. Native Node, Bun, Deno, and Promise boundaries retain narrow documented suppressions where replacing the host API or dependency-ordered layer provisioning would worsen lifecycle semantics. Supersedes #6304
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
… cap (#6365) Refines the AI review pipeline (built in #6358) into its intended shape, and removes the size limit. Validated end-to-end via a temporary self-test trigger during development (now removed — the pipeline ships in shadow mode). ## What changed - **Parallel independent reviews + a dedicated adjudicator.** `claude-review` and `codex-review` now run **in parallel** (Codex no longer depends on Claude); a new **`adjudicate`** job then reconciles both finding sets, verifying each finding by **reading the real code** (PR head checked out read-only), and `post-review` posts the merged result. This replaces the old single Codex job that did both an independent pass and adjudication sequentially — cutting the critical path and giving each job its own timeout. - **No size cap.** Removed the preemptive "too large" guard. The models review agentically (reading the diff and files via their own tools over many turns, like the local CLI), so PRs of any size are reviewed — very large diffs best-effort within the model's context/turn budget. - **Runtime fixes** surfaced by real runs: `gh pr diff --repo` (subdir checkouts), npm config isolation for the Claude CLI install, `set +e` so the Claude retry loop isn't killed by `bash -e`, and the reviewer model set to `claude-opus-5` (the account's API key returns 404 for `claude-fable-5`). Workflow + prompts only for the split (no TS/schema changes — Codex's independent findings reuse `findings.schema.json`; the adjudicator still emits `merged-review.json`). Ships in **shadow mode**: no `pull_request` trigger, only `workflow_dispatch` / maintainer `/ai-review`. ## Notes for reviewers - Two first-run unknowns for the adjudicator (can't verify offline): whether Codex's read-only sandbox can read the `pr/` subtree, and whether it picks up a nested `pr/AGENTS.md` (guarded in the prompt; blast radius bounded — read-only + no network + key-proxied + output-redacted). - Requires the org's Anthropic/OpenAI spend limit to be sufficient, or the model jobs 429. --------- Co-authored-by: Julien Goux <hi@jgoux.dev>
…e on >=1 review (#6380) Follow-up to the AI-review pipeline. Two changes. ## 1. Downgrade `codex-action` v1.12 → v1.11 On the large PR (#6366, ~130k-token diff) the `codex-review` step ran to completion — Codex finished the turn, wrote its output file, printed its final message and token count — then **sat idle until the 45-minute job timeout**, discarding a completed review. That is a confirmed v1.12 regression: **openai/codex-action#150** ("v1.12: Linux run never returns after the turn completes; job dies on timeout with the output file already written"). The reporter confirms **v1.11 handles the same heavy workload cleanly**, and there is no released fix above v1.12. v1.11 (`52fe01ec…`) supports every input we use (`safety-strategy`, `sandbox`, `output-schema-file`, `output-file`, `codex-version`, `working-directory`, `effort`), so this is a drop-in pin change in both Codex jobs. ## 2. Adjudicate on ≥1 independent review (graceful degradation) Previously `adjudicate` required BOTH `claude-review` and `codex-review` to succeed, so one flaky model job sank the whole review. Now it runs when **at least one** independent pass succeeded: each findings download is guarded by its job's result, and the stage step substitutes an empty findings set for any review that didn't complete, so the adjudicator reconciles one or two. The prompt notes the one-review case and records it in its summary. Together: a Codex hiccup no longer wastes a 45-minute run or blocks Claude's (working) review from being posted.
## Summary - prepare `/run/postgresql` for the Linux host UID/GID before the Docker stack drops privileges - preserve the existing root and non-Linux startup paths - cover the privilege-drop ordering with a Linux-specific regression test ## Context The refreshed slim Postgres image listens on a Unix socket under `/run/postgresql`. The stack wrapper bypassed the image root setup when switching to the host user on Linux, so Postgres restarted with a socket lock-file permission error. That readiness failure cascaded into the three e2e startup timeouts visible on #6400.
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com> Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
## Summary - consolidate fragmented Docker coverage into one public 13-service stack journey - verify canonical slim images, representative product behavior, and restart persistence - prove two automatically allocated sibling stacks keep ports, data, ownership, and cleanup isolated ## Context This is a test-only qualification change for CLI-2113. The existing stack implementation already satisfied the complete Docker graph and sibling-isolation contracts; the new journey makes those release-critical guarantees observable through the public package surface.
## TL;DR fixes the CLI rejecting dashboard issued `sbp_v0_` access tokens with `LegacyInvalidAccessTokenError` which was caused by the access token regex pattern only matching the `sbp_` and `sbp_oauth_` prefixes and is now fixed by widening the legacy validator to also accept the `sbp_v0_` prefix... ## ref: - closes: #6348 --------- Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
## Summary Qualifies the first Dockerless native vertical slice through the public `@supabase/stack` surface: isolated native prefetch, lazy and eager activation, real Auth and PostgREST flows, PostgreSQL extensions, restart preservation, retryable typed preparation failure, and exact resource cleanup. Adds a consumer-selected cache root to Promise-based prefetch, exposes the public stack error type, and preserves lazy proxy activation across a whole-stack restart without weakening explicit per-service stops.
## TL;DR fixes `db reset, db lint, db diff`, and `migration down` silently skipping a user schema when its oid also appears in another catalog which was caused by joining `pg_depend` on objid without the `classid` that scopes `oids` to a single catalog now fixed by constraining the join to `pg_catalog.pg_namespace` rows in every copy of the query. Resets now drop schemas that earlier versions silently skipped.... ## ref: - closes: #6375
Adds one sentence to the Pull Requests section of `AGENTS.md`: this repo is public, so PR descriptions, issues, and code comments keep internal content out: absolute production metrics (percentages, ratios, or relative change instead), internal decision detail (vendor, legal, pricing, or strategy discussions), and competitor names (protocol identifiers such as user-agent strings are fine). That context goes in the linked Linear issue. Same rule as the supabase monorepo's agent instructions (supabase/supabase#49750); an agent-authored PR there had quoted absolute internal event volumes in its description.
## TL;DR adds live e2e coverage for the `services` command and `storage mv` ## whats introduced? - `services`: links the project and proves the postgres remote version lands in the json output proves the table renders that value in the LINKED cell, where a plain substring match would pass vacuously - `storage mv`: uploads an object, moves it through the real move endpoint, and proves via the listing that the destination exists and the source is gone closes the storage family, since ls, cp and rm already have coverage - `db pull`: deflakes the shipped live test, pull exits nonzero when nothing changed by design, so the test now seeds remote-only schema through db query and proves the initial pull writes it back as a migration ## ref: - closes: CLI-2263 CLI-2264 CLI-2278
## TL;DR adds live e2e coverage for `migration up` and `migration repair`, closing the migration family... ## whats introduced? - `migration up`: applies a test written migration to the remote database, proven by the apply banner and the history row migration list reads back - `migration repair`: inserts a history row with status applied, proves it through migration list, then removes it with status reverted and proves the absence ## ref: - closes: CLI-2269
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
) ## Summary Adds an opt-in ambient env flag `SUPABASE_USE_SLIM_IMAGES` (`true` or `1`) that rewrites local-stack Docker image names from the embedded Dockerfile pins to the slim `ghcr.io/supabase/cli/` builds. Published slim postgres/storage/auth/edge-runtime images now match the docker.io contracts (root start, `sh`/`wget`), so the flag is an image-name rewrite rather than a second runtime. Spec builders still branch for services that remain distroless (auth/studio/pg-meta healthchecks, pooler/realtime/analytics busybox wget, Vector `secretFiles`). Kong, the `differ`/`migra`/`pgprove` job images, PG14, OrioleDB, historical 15.x pins, and `deno_version = 1` stay on docker.io. Slim refs skip `SUPABASE_INTERNAL_IMAGE_REGISTRY`. With the flag unset, image *names* stay on docker.io. This PR also bumps the shared Dockerfile pins (flag-off and flag-on use the same versions) and syncs stack `DEFAULT_VERSIONS`: - postgres `17.6.1.165` → `17.6.1.167` - postgres 15 fallback `15.8.1.085` → `15.14.1.167` (slim-services [#290](supabase/slim-services#290); published as `ghcr.io/supabase/cli/postgres:15.14.1.167`) - pooler `2.9.7` → `2.9.12` - realtime `v2.129.9` → `v2.130.0` - storage `v1.71.0` → `v1.72.1` Majors 13/15 slim-translate that current PG15 pin when the flag is on. Storage `v1.72.1` prefers `IMAGE_TRANSFORMATION_ENABLED` over `ENABLE_IMAGE_TRANSFORMATION`, so the CLI now emits both keys on every Storage spec (not slim-only). The rewrite always targets `ghcr.io/supabase/cli/`. The stack catalog's vector/pooler mirrors (`ghcr.io/supabase/{vector,supavisor}`) are not used. This is the code layer of a stack that splits the previous mixed review on #6329. Docs live in #6383. ## Linked issue Closes # - [x] The linked issue is **open** and carries the `open-for-contribution` label (or I'm a Supabase maintainer). ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/) (e.g. `fix(cli): …`). - [x] Tests added or updated for the change. - [ ] From the repository root, `pnpm check:all` passes; relevant package tests pass for every touched workspace, and `pnpm types:check` passes for each touched TypeScript workspace (or workspace declaring it). --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary Records `SUPABASE_USE_SLIM_IMAGES` on every legacy command whose image resolution the flag reaches, so `SIDE_EFFECTS.md` matches the resolver. Current contract: - Ambient `process.env` only (`true`/`1`) — not project dotenv. - Current Dockerfile pins rewrite to `ghcr.io/supabase/cli/`. Slim refs skip `SUPABASE_INTERNAL_IMAGE_REGISTRY`. - Kong, job images (`differ`/`migra`/`pgprove`), PG14, OrioleDB, historical Postgres pins, and `deno_version = 1` stay on docker.io. - Majors 13/15: flag-off keeps `15.8.1.085`; flag-on slim-translates the published `15.14.1.167` pin. - Slim postgres/studio/pg-meta/edge-runtime keep the docker.io probes (`pg_isready` / `node`). Slim analytics still uses the docker.io start spec (`./logflare` wrapper and BigQuery bind). - Slim auth, storage, vector, realtime, analytics, and pooler ship BusyBox wget (not GNU wget, not curl). In-container HEALTHCHECK is `wget -q --spider` (realtime also `--header Host:realtime-dev`). Vector's Logflare wait is `wget -q -T 2 --spider`. Flag-off docker.io wget stays `--no-verbose --tries=1 --spider`. - Storage emits both `ENABLE_IMAGE_TRANSFORMATION` and `IMAGE_TRANSFORMATION_ENABLED`. - Same-tag slim vs docker.io family mismatch remediates with `supabase stop` then `supabase start` (same flag). `stop --all --no-backup` stays for a real version mismatch. Stacked on #6382 so reviewers see a docs-only diff. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…an shadows (#6215) ## Summary Rebased onto `develop` now that #6102, #6184, and #6203 are merged. The PR is only the plan-shadow overlap — not the lower-stack cache/stop work. A declarative sync provisions two shadow databases (migrations + declarative). Those used to run strictly sequentially, so the declarative shadow's whole provision was **added** to the runtime instead of overlapping it. Provisioning now peeks each shadow's baseline-cache state (`legacyPeekShadowBaseline`) and picks one of three strategies (`legacy-pgdelta-next-shadow.plan.ts`): - **`parallel`** — both snapshots already published: both warm-restore concurrently. A warm restore skips the platform baseline, so only the migrations fiber prints (`Applying migration ...`), live and in order. - **`baseline-handoff`** — first run, both cold under one cache key: the platform baseline is built once. The migrations shadow cold-provisions; its snapshot export at the baseline seam signals the declarative fiber, which warm-restores from the just-published tar concurrently with migration replay. A handle that will never snapshot signals immediately, and the runner `Effect.ensuring`s the signal onto the whole provision as a liveness backstop. - **`sequential`** — different keys, mixed states, `--no-cache`, cache env off, PG≤14/OrioleDB: no baseline can be shared, so this keeps the pre-parallel flow and transcript. **Output ordering is a hard guarantee.** In the concurrent strategies the declarative fiber's `Output` writes go through `legacyBufferedShadowOutput` and flush after the join. Post-flush writes pass through live so late teardown warnings are never lost. Same-database identity still uses the **acquired** handles' `snapshotKey`s (not the peeks), so a delayed declarative re-resolve cannot lie about snapshot lineage. Supporting cache changes: - `legacyPeekShadowBaseline` answers "what would the acquire do right now" without provisioning. The acquire always re-checks disk state. - Immediate acquires reuse peeked key inputs via `precomputedKeyInputs` so the JWKS discovery request is not resolved twice. Delayed declarative acquires re-resolve so a mid-run `roles.sql` edit cannot publish under a stale key. - Cold snapshot exports are serialized by an in-process mutex (`legacyExportPgDataTar`'s temp name is pid-scoped). The absent-at-acquire dedupe skips a re-export only when the tar appeared after the cold acquisition began; a tar retained through a failed warm restore is still atomically replaced. Dogfooded this PR against its merge base (`develop@38f31b4`) on `supabase db schema declarative sync --no-apply --experimental` (pg-delta next), full 2×2 matrix of {base, PR} × {`SUPABASE_SHADOW_CACHE` off/on}, 5 timed runs per cell plus extra cold-cache samples. All docker images pre-pulled and the local stack already running, so no run pays pull or stack-start cost. Times are full CLI wall-clock on a converged project ("No schema changes found" — both shadows still provisioned every run). | Scenario | develop (base) | this PR | Delta | |---|---|---|---| | `SUPABASE_SHADOW_CACHE=0` | 21.96s ± 0.42 (n=5) | 22.32s ± 0.61 (n=5) | none (within noise) | | `SUPABASE_SHADOW_CACHE=1`, cold cache | 16.02s ± 0.66 (n=4) | 16.18s ± 0.38 (n=4) | none (within noise) | | `SUPABASE_SHADOW_CACHE=1`, warm cache | 6.71s ± 0.49 (n=4) | **5.25s ± 0.14** (n=4) | **−1.46s, 21.8% faster (1.28×)** | Per-run warm values — base: `6.03, 6.80, 6.79, 7.21` · PR: `5.38, 5.14, 5.12, 5.35`. The PR is also noticeably less noisy (σ 0.14 vs 0.49). Co-authored-by: Claude <noreply@anthropic.com>
## Summary Bumps the pinned pg-meta image from `v0.98.0` to `v0.99.0` in the shared service-image manifest (`apps/cli-go/pkg/config/templates/Dockerfile`, imported by the TypeScript CLI as its image source). postgres-meta v0.99.0 replaces the embedded type-generation templates with the shared [`@supabase/postgrest-typegen`](https://github.com/supabase/sdk/tree/main/packages/postgrest-typegen) package (supabase/postgres-meta#1084). This is part of a coordinated rollout with the hosted path (supabase/platform#37764) so `gen types` produces the same output locally and via `--project-id`. ## Relationship to #6404 #6404 makes `gen types` run postgrest-typegen in-process, removing the pg-meta container from that command entirely. This pin still matters independently of it: the same manifest entry provides the `pgmeta` service that `supabase start` runs for Studio's local API, and it covers `gen types` for any release cut before #6404 lands. The two do not conflict (different files), and output is consistent either way since v0.99.0 serves the same generator package that #6404 embeds. ## What changes for users Generated TypeScript output changes in two deliberate ways: deterministic metadata ordering (a one-time reordering diff when regenerating existing types) and oxfmt formatting instead of prettier (style-only). Content is otherwise unchanged. ## Validation - `go build ./...` passes in both modules. - The pre-existing `gen types` e2e tests pull this image tag directly, so CI exercises the new release; the image is published on Docker Hub and ECR Public.
This PR was automatically created to sync the generated `@supabase/api` package with the latest Management API OpenAPI document. Changes were detected in the upstream OpenAPI documents exposed by `https://api.supabase.com/api/v1-json` and `https://api.supabase.com/api/v2-json`. Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com> Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
## Summary Changes the shadow baseline cache (`SUPABASE_SHADOW_CACHE`) from opt-in (default OFF) to opt-out (default ON). This improves performance for `db diff`, `db pull`, and schema declarative operations by caching the baseline PGDATA snapshot by default, while allowing users to disable it by explicitly setting `SUPABASE_SHADOW_CACHE=0` or `false`. ### Key Changes 1. **Environment variable semantics**: `SUPABASE_SHADOW_CACHE` now defaults to enabled when unset. Setting it to any non-viper-true value (`0`, `false`, empty, or garbage) disables the cache. 2. **New `whenUnset` option**: Extended `legacyViperEnvBoolWithProjectFallback` with an optional `whenUnset` parameter that resolves unset keys to a specified boolean, enabling opt-out gate semantics while preserving exact `ParseBool` behavior for present values. 3. **Updated documentation**: All SIDE_EFFECTS.md files and code comments reflect the new default-ON behavior and opt-out mechanism. 4. **Test coverage**: Added tests for the new `whenUnset` option, flipped the default-gate integration test to assert the default-ON cold export + warm restore, and added a project-dotenv opt-out test. ### Behavior - **Unset or true**: Cache is enabled (cold run snapshots baseline, warm runs restore from snapshot) - **Explicitly set to `0`/`false`/empty/garbage**: Cache is disabled (uncached create/remove pair, identical to old default) - **Project dotenv support**: The setting is honored from both shell environment and project `.env` files - **`sync --no-cache`** still bypasses restore and publish per invocation Users who explicitly disabled the cache keep their behavior; all other runs now leave up to 3 ~90MB baseline tars (2-day TTL) under `~/.supabase/cache/shadow-baseline/`. ## Linked issue Closes # - [x] The linked issue is **open** and carries the `open-for-contribution` label (or I'm a Supabase maintainer). ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/) (e.g. `fix(cli): …`). - [x] Tests added or updated for the change. - [x] From the repository root, `pnpm check:all` passes; relevant package tests pass for every touched workspace, and `pnpm types:check` passes for each touched TypeScript workspace (or workspace declaring it). https://claude.ai/code/session_01Uj7BjiXEnbcWy41ToxCnPs 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary Prefetch and version unit tests were pinning published pgmeta and vector image tags. Those assertions fail whenever `ServiceCatalog.ts` and the template Dockerfile are bumped. The tests now derive the expected images from `DEFAULT_VERSIONS` / `dockerImageForService`, matching the other catalog-backed cases in the same files. ## Linked issue No linked issue — test-only maintenance so image bumps do not fail unrelated unit tests. Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <cursoragent@cursor.com>
Add a `supabase experimental` command family, registered with `Command.unlisted`, and move `workers` underneath it so the family stays invocable but is explicitly marked unstable and excluded from help, shell completions, the wizard, and generated docs. - Add `legacy/commands/experimental/experimental.command.ts` as the new unlisted parent and mount it in `root.ts`, replacing the direct `workers` registration - Relocate the `workers` command tree (`delete`, `list`, `new`, `push`, `status`, shared helpers, and tests) under `experimental/workers/`, updating relative imports accordingly - Update every user-facing invocation string (examples, suggestions, error messages, comments) in handlers, tests, and shared worker utilities from `supabase workers ...` to `supabase experimental workers ...` - Drop the `supabase-workers` entries from the legacy docs tables so the family no longer appears in generated docs --------- Co-authored-by: Kanad Gupta <git@kanad.dev>
…n /apps/cli-go in the go-minor group across 1 directory (#6412) Bumps the go-minor group with 1 update in the /apps/cli-go directory: [github.com/posthog/posthog-go](https://github.com/posthog/posthog-go). Updates `github.com/posthog/posthog-go` from 1.23.1 to 1.24.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/posthog/posthog-go/releases">github.com/posthog/posthog-go's releases</a>.</em></p> <blockquote> <h2>1.24.0</h2> <h2>Unreleased</h2> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/PostHog/posthog-go/blob/main/CHANGELOG.md">github.com/posthog/posthog-go's changelog</a>.</em></p> <blockquote> <h2>1.24.0</h2> <h3>Minor Changes</h3> <ul> <li>150f03e: Fall back to <code>/flags</code> when a requested flag is missing from loaded local definitions. This changes the earlier behavior where the key was omitted without a request.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/PostHog/posthog-go/commit/2eaba7155afd758bf9027371a6f9ee9a9b5f6bcf"><code>2eaba71</code></a> chore: release v1.24.0 [version bump] [skip ci]</li> <li><a href="https://github.com/PostHog/posthog-go/commit/35100f0aace345e153da3e1d284d56f71c96f8f7"><code>35100f0</code></a> fix(release): gate released Slack notification on an actual release (<a href="https://redirect.github.com/posthog/posthog-go/issues/293">#293</a>)</li> <li><a href="https://github.com/PostHog/posthog-go/commit/bded1a0e9f9ba01e22f0fac12997ba2a53ff34fb"><code>bded1a0</code></a> fix(release): opt private package into changesets v3 versioning (<a href="https://redirect.github.com/posthog/posthog-go/issues/292">#292</a>)</li> <li><a href="https://github.com/PostHog/posthog-go/commit/150f03e2ec5e034f5a0a219bd46545bcaa55a147"><code>150f03e</code></a> fix(flags): fall back for missing local definitions (<a href="https://redirect.github.com/posthog/posthog-go/issues/286">#286</a>)</li> <li><a href="https://github.com/PostHog/posthog-go/commit/fd8580e08c50150a2c27e6941fa9717326dd94dc"><code>fd8580e</code></a> chore(deps): bump the github-actions group with 3 updates (<a href="https://redirect.github.com/posthog/posthog-go/issues/290">#290</a>)</li> <li><a href="https://github.com/PostHog/posthog-go/commit/176cbdca624348e82d56a26c305ec724eef78759"><code>176cbdc</code></a> chore(deps-dev): bump <code>@changesets/cli</code> from 2.31.1 to 3.0.0 in the release-too...</li> <li><a href="https://github.com/PostHog/posthog-go/commit/803058843e9b42b54eec13c077c3e7286064bc0d"><code>8030588</code></a> chore: update flags project workflow caller (<a href="https://redirect.github.com/posthog/posthog-go/issues/287">#287</a>)</li> <li><a href="https://github.com/PostHog/posthog-go/commit/d0ba449b96cf32bd34ff272441c01f0418f20a82"><code>d0ba449</code></a> test: expand server SDK wire snapshots (<a href="https://redirect.github.com/posthog/posthog-go/issues/285">#285</a>)</li> <li>See full diff in <a href="https://github.com/posthog/posthog-go/compare/v1.23.1...v1.24.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95f0c2bfac
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const entries: Record<string, string> = { | ||
| should_run: String(result.shouldRun), | ||
| pr_number: String(prNumber), | ||
| head_ref: `refs/pull/${prNumber}/head`, |
There was a problem hiding this comment.
Pin the review run to one head SHA
Capture the PR's immutable head.sha here instead of exporting the mutable refs/pull/<n>/head. These reviews can run for up to an hour, and the Claude job, independent Codex job, adjudicator, and posting code each resolve or fetch the PR at different times; if another commit is pushed during the run, they can review different revisions and ultimately post incomplete or stale findings against the newest diff. Export the resolved SHA and either use it for every checkout/diff or abort before posting when the PR head has changed.
Useful? React with 👍 / 👎.
| (github.event_name == 'issue_comment' && github.event.comment.body != '/ai-review') | ||
| && github.run_id || 'review' }} |
There was a problem hiding this comment.
Normalize valid commands in the concurrency key
Use the same normalization as the resolver when deciding whether this is an /ai-review command. The resolver accepts a trimmed first line, so /ai-review and /ai-review\n... are valid requests, but this full-body equality assigns each one a unique github.run_id group. Consequently, repeated valid requests in those forms do not cancel the in-flight review and can run multiple expensive pipelines that race to post and supersede each other's output.
Useful? React with 👍 / 👎.
| ); | ||
| } | ||
|
|
||
| await supersedePriorRunsBestEffort(io, prNumber); |
There was a problem hiding this comment.
Exclude the review that was just posted
The successful POST is followed by a fresh listReviews call, but supersedePriorRuns updates every unsuperseded marker-bearing review by github-actions[bot] and has no ID or body exclusion for the review just created. Once GitHub returns that new review in the list—which is the normal result of querying after creation—the pipeline immediately wraps its own current review as “Superseded by a newer AI review.” Capture the prior entries before posting or return the created review ID and exclude it.
Useful? React with 👍 / 👎.
| const marker = `\n\n… (truncated — see workflow run: ${runUrl})`; | ||
| return body.slice(0, GITHUB_REVIEW_BODY_MAX - marker.length) + marker; |
There was a problem hiding this comment.
Preserve the review marker when truncating
When a rendered review exceeds the limit, this slices off its tail and appends only the visible truncation notice. Because AI_REVIEW_MARKER is emitted at the very end of the original body, oversized reviews are posted without the marker, so the automatic dedup check cannot recognize them and later manual runs cannot supersede them. Include the hidden marker in the reserved truncation suffix.
Useful? React with 👍 / 👎.
| name: AI Review | ||
|
|
||
| # One-shot AI code review: replaces the Codex GitHub App's automatic | ||
| # per-push reviews (which churned 30-40 short rounds per PR) with a single |
There was a problem hiding this comment.
Remove the internal review-volume metric
Replace the exact “30-40” review-round count with a qualitative statement. This workflow is committed to the public repository, while the repository guidance explicitly prohibits publishing absolute internal event counts in code comments and directs that context to the private issue tracker instead.
AGENTS.md reference: AGENTS.md:L276-L276
Useful? React with 👍 / 👎.
| permissions: | ||
| pull-requests: write |
There was a problem hiding this comment.
Grant contents read access to the posting job
Add contents: read to this job's permissions. The workflow-level permissions: {} disables every unspecified token scope, and this job currently grants only pull-requests: write, yet its first step checks out develop; actions/checkout requires repository contents read access, so the job can fail before it downloads or posts the completed review.
Useful? React with 👍 / 👎.
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
| return redactSecrets(text) | ||
| .replace(HTML_COMMENT_PATTERN, "") |
Ends the AI review pipeline's shadow mode: the `pull_request` trigger (`opened` / `ready_for_review`) in `ai-review.yml` is now live, so every qualifying PR gets its one-shot Claude + Codex review automatically. The automatic path is gated to internal contributors. On top of the existing draft/bot/fork skips, `resolve.ts` now resolves the PR author's effective repository permission and requires `write`/`admin` (the same `WRITE_PERMISSIONS` gate the manual `/ai-review` path already uses) before running. This lookup is the authoritative author check — a same-repo head branch only proves the branch exists in the repo, not that the author pushed it — and an unresolvable permission counts as unauthorized. External contributors' PRs are never reviewed automatically; a maintainer comments `/ai-review` to request one, exactly as before. The gate runs before the dedup listing (one permission lookup instead of two paginated list calls), and `PrDetails` now carries the author's login so the resolver can do the lookup. The README's rollout section is rewritten to document the live trigger and the note that the Codex GitHub App's automatic reviews must stay disabled so PRs aren't double-reviewed. Two fixes surfaced by this PR's own live run: - **Fresh reviews no longer supersede themselves.** `postConsolidatedReview` listed reviews *after* posting, so the just-posted review (a marker-bearing bot review) was swept into its own supersede pass and every new review immediately collapsed as "Superseded by a newer AI review". The prior runs are now snapshotted before the POST, and the test fake mirrors real GitHub by including posted reviews in later listings. - **Auto runs get their own concurrency group.** `pull_request` events now use a per-PR `auto` group instead of sharing the manual `review` group, so a `ready_for_review` event (whose run may resolve to a skip) can never cancel an in-flight maintainer-requested review. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…234, CLI-2232) (#6366) Closes CLI-2234 Closes CLI-2232 ## What changed Prepares `@supabase/config` for its first npm publish: the export surface is audited and trimmed (CLI-2234) and the package gains a real compiled build (CLI-2232). One PR because the audit decides what the entrypoints contain and the build compiles exactly that, and the audit's type-surface enforcement (API report) only works once the build emits `.d.ts`. ### Export-surface audit (CLI-2234) Every export got an explicit keep / move / trim decision: | Decision | Symbols | | --- | --- | | **Moved to `apps/cli`** | `KONG_LOCAL_CA_CERT` (+ its test) — a local-stack TLS asset, not config schema | | **Moved to new `./internal` subpath** (explicitly not semver-covered; enforced apps/cli-only) | `ENV_CAPTURE_REGEX`, `AUTH_HOOK_NAMES`, `unmappedSecretApiPaths`, `projectConfigMappingRows`, `ProjectConfigMappingRow`, `ProjectConfigApiAttributes`, `InternalLoadCliConfigOptions` + goViperCompat-capable typings of `loadCliConfig`/`resolveCliConfigValue`/`resolveCliConfigSubtree` | | **Removed from public options** | `goViperCompat` (off `LoadCliConfigOptions`; resolvers lost their options param entirely — re-adding later is non-breaking) | | **Trimmed** | `MissingCliConfigValueError` deleted entirely (never constructed anywhere in the package; apps/cli only carried a telemetry mapping entry + a test that fabricated one — both removed), `loadCliConfigFile`/`InternalResolveCliConfigOptions` off the internal barrel (zero consumers) | | **Renamed** (`./io`, zero consumers existed) | `findCliProjectRootFor→findCliProjectRoot`, `findCliProjectPathsFor→findCliProjectPaths`, `loadCliProjectEnvironmentFor→loadCliProjectEnvironment`, `loadFunctionsManifest→inferFunctionsManifest` — `./io` now mirrors `./effect` 1:1; the subpath conveys Promise-vs-Effect | | **Added** | sync `resolveCliConfigValue`/`resolveCliConfigSubtree` on `.` (Effect-typed variants deliberately shadow them on `./effect`); `ProjectConfigSchema` (runtime, Standard Schema v1 via `Schema.toStandardSchemaV1` — one symbol serves Effect-native and `~standard` consumers); `toProjectConfigJsonSchema`; `PROJECT_CONFIG_SCHEMA_URL` | | **Kept** (documented contract in README) | schema/types, encoders, defaults + sparse helpers, the ProjectConfig converters (`toProjectConfig`, `fromConfigDocument`, `fromApiProjectConfig`, `attachApiResponse`, `comparableProjectConfigPaths`, `unmappedApiFields`), errors, functions-manifest model | `ProjectConfigSchema` is derived from `CliConfigSchema` at the AST level (hosted sections → type-side → deep-optional → `x-secret` leaves dropped → cross-field checks stripped, leaf checks kept) with a two-way compile-time assignability pin against the `ProjectConfig` type, so the runtime schema and the type cannot drift. `./io`'s error channel is narrowed from `unknown` to the exact five-member union (verified exact by review: no wider member, none unused). ### Compiled build (CLI-2232) - Plain `tsc` (tsgo 7.0.2, `nodenext` + `rewriteRelativeImportExtensions`) emits ESM `.js` + `.d.ts` + maps to `dist/`; no bundler. - Conditional `exports`: in-repo Bun resolves `src/*.ts` (with `customConditions: ["bun"]` so tsc typechecks against source, not stale dist); external consumers get `dist` js + types. - Tarball sealed via `files` + `.npmignore` (npm-packlist otherwise applies the root `.gitignore` and ships no `dist` — `npm pack` and `pnpm pack` now agree); publish metadata (license, repository, publishConfig, engines) added; peers widened to `>=4.0.0-rc.111 <5`. - `sideEffects: false`, proven by a tree-shake probe with positive + negative controls against the built artifact. - `dist/project-schema.json` joins `dist/schema.json` (both draft-2020-12, now with `$id`/`title`, and with Effect's non-finite-number `anyOf` encoding collapsed so numeric fields keep `description`/`default`). - The docs site now publishes those same built artifacts verbatim (`generate-docs.ts` copies `dist/*.json` to `apps/docs/public/cli/{config,project-config}.schema.json`; docs generate `dependsOn` the package build) — one post-processed source of truth, and both `$id` URLs resolve once deployed. - Workspace test runners resolve the `bun` export condition (`resolve.conditions`/`ssr.resolve.conditions` in the vitest configs), so vitest exercises `src` — never a stale or absent `dist` (caught by the AI review: previously tests resolved the `default` → `dist` branch). - Build ends with a pack-and-install smoke test: real `npm pack` → temp install → real `node` imports every subpath. ### Enforcement (surface changes stay deliberate) - Sealed exports map, pinned key set at runtime. - Per-entrypoint export-name snapshots (now incl. `./internal`), purity walker over `index.ts` and `io-browser.ts`. - Type-surface changes: `pnpm run check:config-api` (root task; advisory `continue-on-error` CI step) emits declarations for the PR base and head — base source extracted via `git archive` into the package dir so the current install resolves deps, no second install — and reports the `.d.ts` diff in the job summary. Per-PR signal, zero committed artifacts. The **hard** gate moves to release time (CLI-2233): diff the new `dist/*.d.ts` against the previously published tarball's in the human-approval step. - `@supabase/config/internal` imports enforced apps/cli-only. ## Review rounds Three internal reviews (engineer, architect, DX-as-consumer incl. a clean-Node tarball install exercising 23 checks) ran before this PR; all accepted findings are in the final commit. Explicitly rejected, for the record: - `@deprecated` markers on `./internal` exports (strikethrough noise across apps/cli's own legitimate call sites; the no-semver contract is documented at the barrel, README, and AGENTS.md). - `message` getters on the tagged error classes (would change CLI-visible error output pinned by normalize-error tests; README documents the structured-fields contract instead — candidate follow-up). - A checked-in `api-report/` `.d.ts` mirror (53 files + freshness test) existed in earlier commits of this branch and was removed by owner decision — per-PR accept semantics weren't worth 580 KB of generated diff noise. Replaced by the advisory base-vs-head compare above; an api-extractor-style rollup was also considered and skipped (TS7/tsgo compatibility unproven). - `saveCliConfig`'s atomic-write rename failure stays a defect (documented); re-channeling it as a typed failure is a behavioral follow-up. - Moving `KONG_LOCAL_CA_CERT` to `packages/stack` (single legacy consumer today; speculative second move). ## Known collateral: `@supabase/pg-topo` under `customConditions` `customConditions: ["bun"]` in `apps/cli/tsconfig.json` (needed so tsc typechecks `@supabase/config` against source instead of gitignored `dist/`) also changes resolution for `@supabase/pg-topo`, whose own `bun` exports condition points at unbuilt `src/*.ts` carrying 3 type errors at `1.0.0-alpha.5`. Worked around with a commented `paths` pin to its shipped `dist/index.d.ts`. `1.0.0-alpha.6` is published but currently blocked by pnpm's `minimumReleaseAge`; once it ages in, bump it in `apps/cli` and drop the pin (and the `bun`-condition source errors deserve an upstream fix in `supabase/pg-toolbelt` either way). ## Notes for CLI-2233 / CLI-2169 (publish) - The release pipeline must diff the new `dist/*.d.ts` against the previously published tarball's and surface that diff in the human-approval step — that is the hard semver gate (the PR-time compare above is advisory only; first publish trivially has no compare target). - Publish with `pnpm publish` (only pnpm rewrites any residual `catalog:`; peers are now literal ranges regardless). - `effect@latest` is still 3.x — README instructs `effect@rc`; revisit ranges when Effect 4 goes stable. - No top-level `main`/`types` (deliberate ESM + exports-only; node10 resolution unsupported). - Pre-existing `@supabase/cli-go#lint:check` gosec findings fail local `check:all` on clean develop too — untouched by this PR.
| - name: Run Claude review | ||
| working-directory: trusted | ||
| env: | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} |
There was a problem hiding this comment.
🟡 Severity: MEDIUM
On a maintainer-requested review of a fork, the PR is untrusted but this step places ANTHROPIC_API_KEY in Claude's environment while allowing Read. Prompt-injected PR text can direct Claude to read /proc/self/environ, encode the key to evade regex-only redaction, and publish it through the public review or artifact.
Helpful? Add 👍 / 👎
💡 Fix Suggestion
Suggestion: The root issue is that ANTHROPIC_API_KEY must remain in Claude's environment for authentication, so the key itself cannot be removed from line 205. Instead, three complementary mitigations should be applied at different locations:
-
Path-restrict the
Readtool (line ~220 in same file): The Claude CLI supports directory-scoped tool restrictions. Change--allowedTools "Read,Grep,Glob"to restrictReadto only the PR workspace and temp review files — e.g.,--allowedTools "Read($GITHUB_WORKSPACE/pr/**:/tmp/ai-review/**)"(verify exact path-restriction syntax against the installed claude-code version). This prevents a prompt-injected instruction from directing Claude toRead("/proc/self/environ")or any path outside the intended scope. -
Strengthen the redaction layer (in
.github/scripts/ai-review/post-review.ts): The currentSECRET_PATTERNSregexes inredactSecretsonly match rawsk-ant-...substrings. A prompt injection can instruct Claude to base64-encode or hex-encode the key before including it in a finding, evading these patterns entirely. Add post-processing that attempts to detect common single-step encodings: decode every base64-looking substring (matching[A-Za-z0-9+/]{20,}={0,2}) in model output and run the secret patterns against the decoded form; if a match is found, redact the encoded original. Also look for hex sequences of sufficient length. -
Long-term: use an API proxy or short-lived token: Eliminate the raw
ANTHROPIC_API_KEYfrom the runner environment entirely by routing Claude's API calls through a purpose-built proxy (e.g., a Lambda or Cloud Function) that holds the real key server-side and accepts a short-lived, spend-capped, IP-restricted token scoped to this workflow. Even if the token is exfiltrated, it cannot be used outside the CI IP range and expires quickly.
…CLI-2233) (#6381) Closes CLI-2233 Stacked on #6366 (compiled build + trimmed surface) — review only the top three commits until that merges. ## What changed `@supabase/config` gets its own release train, fully independent of the CLI's semantic-release flow: `.github/workflows/release-config.yml`, triggered only by pushes to `develop` touching `packages/config/**`. ### Version computation (plan job) - A second semantic-release instance (catalog-pinned devDep, driven through the JS API by `packages/config/scripts/release-plan.ts`) with `tagFormat: config-v${version}` — semantic-release's tag matching is anchored, so the `config-v*` and CLI `v*` trains can't see each other's tags (verified in both directions against the installed v25 source). - Commit analysis is path-filtered to `packages/config/**` by an in-repo plugin (`scripts/semantic-release-path-filter.ts`): one batched `git diff-tree --stdin -r --root --name-only -z` call, then delegation to the real `@semantic-release/commit-analyzer`/`release-notes-generator`. `semantic-release-monorepo` was considered and rejected (last published Feb 2024, unproven against v25's ESM internals); the wrapper is small and unit-tested, including the case that justifies its existence — a breaking change outside `packages/config/` must not produce a major — plus merge-commit, root-commit (`--root`), and non-ASCII-path (`-z` vs `core.quotePath`) edges. - The plan refuses to run without a baseline `config-v*` tag: with none, semantic-release would cut `1.0.0` with notes generated from the entire monorepo history — a whole-history changelog as the approval artifact. Escape hatch: `CONFIG_RELEASE_ALLOW_NO_BASELINE=1`. - While `private: true` (until CLI-2169 flips it), the plan job still runs everything — version, gate, pack — and reports `blocked_on_private`; every config push to develop rehearses the plan half of the train while publishing nothing. ### The release-time hard gate (deferred here from #6366) `tools/config-release-gate.ts` diffs the freshly built `dist/**/*.d.ts` against the previously published npm tarball's declarations and writes the diff to the job summary, with semver-sanity warnings (surface changed on a patch bump; a `.d.ts` file removed, or declaration lines removed from an existing one, on a non-major bump). It shares its diff machinery with the PR-time advisory compare via a new `tools/lib/dts-diff.ts` (behavior-preserving extraction from `tools/config-api-compare.ts`, verified byte-identical output). The gate itself never fails on a diff — the human approving the `config-release` environment, with the plan job's summary in front of them, IS the gate. Handled explicitly: first publish (E404, parsed from `npm view --json`, not substring-matched), a published tarball with no `dist/` (warns instead of blocking every subsequent release), an unparseable published version (bump class degrades to "unknown" instead of exit 2). Downloaded tarballs are verified against the registry's `dist.integrity`, refused if their URL points off-registry, and extracted with `--no-same-owner --no-same-permissions`. ### Publish job — the approved bytes are the published bytes The plan job packs the tarball the gate evidence describes and uploads it as a workflow artifact; the publish job downloads that exact tarball, verifies it (`dist/index.js` present — the `.gitignore`/packlist trap, name/version match, `private` not true), and publishes its extracted content with `pnpm publish --provenance --tag latest --no-git-checks`. No `pnpm install` and no build run in the job that holds `id-token: write` — the only repo code it executes is the workflow file itself. The rest mirrors `release-shared.yml`'s hardened posture: github-hosted runner (npm provenance rejects self-hosted), OIDC trusted publishing (no NPM_TOKEN), idempotent registry probe and idempotent `config-v*` tag push, GitHub Release from the semantic-release notes with `make_latest: "false"` so a config release can never hijack the `releases/latest/download/...` URLs the CLI install scripts and setup-cli resolve. Approval-evidence integrity: the plan job asserts the `config-release` environment actually has a required-reviewers rule before a real release can reach the publish job (auto-created environments have no protection rules); semantic-release's commit-derived stdout is bracketed with `::stop-commands::` so a crafted commit message can't issue workflow commands (e.g. `::add-mask::` over the gate output); and everything commit- or registry-derived that lands in the step summary is rendered inside dynamically-sized fences with HTML-escaped paths, so a fenced code block in a JSDoc comment or PR title can't forge the approver's evidence. `package.json`'s `version` is never committed; it's set at pack time from the computed version, same convention as the CLI's own train. ## Decisions (flagging for override) - **semantic-release, not changesets** — one release philosophy per repo; the commit discipline (conventional commits, squash-merge) already carries the signal. - **Single channel:** stable-only from `develop`, npm dist-tag `latest`, no beta/alpha and no git-notes channel machinery. The CLI's three channels exist for binary distribution rings; a library doesn't need them, and adding a prerelease branch later is additive. - **No release-notes rewrite stage** — raw path-filtered commit-analyzer notes go straight to the GH release; the CLI's Claude-rewrite pipeline is product-flavored and stays CLI-only. - **No brew/scoop/smoke/install-verify jobs** — nothing here ships binaries. - **No `version` input on workflow_dispatch** — the registry probe makes re-runs idempotent, and with no binary artifacts plus a human approval in the loop, the CLI's cut-forward escape hatch isn't worth a second code path; recovery is "land a new releasable commit". ## One-time setup before the first real publish (CLI-2169) Documented in `packages/config/AGENTS.md` → "Releases": 1. Required reviewers on the `config-release` environment (the plan job fails closed until this exists). 2. npm trusted publishing needs the package to exist: first publish is a manual bootstrap with a granular single-package short-expiry token (revoked immediately after), then the trusted publisher is set to repo `supabase/cli`, workflow `release-config.yml`, environment `config-release`. 3. Push a baseline tag (e.g. `config-v0.1.0`) — required, see above. 4. A repository tag ruleset protecting `config-v*` (the last tag is the version oracle). ## Also here: npm-page README pass (CLI-2169, second commit) Quickstart moved to the top with a pure-entrypoint example, the remaining relative links made absolute, the semver section now describes the live release pipeline instead of "planned under CLI-2233", Development section labeled contributor-facing, License section added, no bare issue IDs left. ## Review Engineer and security reviews both ran before this PR; every blocking and medium finding is fixed in the third commit (artifact handoff, gate-armed assertion, markdown-fence injection, `-z` path quoting, dist-less tolerance, baseline guard, tarball integrity/origin checks, stop-commands bracketing, version-shape validation, notes trailing-newline). Noted but deliberately not done: - The CLI's own train still analyzes config commits (a `feat(config):` bumps the CLI version too, as it always has) — the "vice versa" half of the filtering would change the CLI's established release behavior and deserves its own issue. - The publish half stays unexercised until `private` flips — the first real publish is also the first execution of the OIDC path, which is why the bootstrap in AGENTS.md is manual and deliberate. - `~/.releaserc` leakage into local `release-plan.ts` runs (cosmiconfig searches up to `$HOME`): harmless in CI, where no such file exists.
## Summary Adds `.github/workflows/mirror-slim-image.yml`, the handler for the `mirror-slim-image` `repository_dispatch` event sent by the `supabase/slim-services` release pipeline (contract: `docs/design/ecr-mirror-dispatch.md` in that repo). It mirrors `ghcr.io/supabase/cli/<service>:<version>` to `public.ecr.aws/supabase/cli/<service>:<version>`, reusing the AWS credentials and mirror conventions already in this repo (`PROD_AWS_ROLE` via `configure-aws-credentials`, region `us-east-1`, `docker/login-action` for ECR Public and ghcr.io, SHA-pinned actions). No new secrets or roles. Key behavior: - **Untrusted payload validation**: the dispatch payload arrives with whatever authority holds the dispatch token, so `service`/`version`/`digest` are pattern-checked, `source`/`destination` are derived from `service` + `version` rather than trusted, and the event is rejected if the payload strings disagree with the derived values. The source tag must resolve to the claimed index digest before anything is copied. - **Digest-preserving copy**: uses `regctl image copy` (pinned v0.11.5 binary, checksum-verified), which moves the whole OCI index — all platform manifests plus referrers — byte-for-byte, and copies by digest so a tag move on the source can't race the copy. The sender polls the ECR destination anonymously (15-minute timeout) and fails its release if the digest never matches, which is why `docker buildx imagetools create` (used by the existing docker.io mirror) is unsuitable here: it can rewrite the index and change its digest. - **Idempotent**: re-dispatches are safe and exit successfully with the destination digest unchanged. The copy runs unconditionally rather than early-exiting on a matching destination digest: regctl's copy is incremental, so a re-dispatch after a complete copy is a cheap verification pass, while a re-run after a partial failure (root index pushed but referrers/digest-tags missing) completes the copy instead of skipping it. A `concurrency` group keyed on service+version (`cancel-in-progress: false`) keeps re-dispatches from racing. - **Repository provisioning**: ensures the ECR Public repository `cli/<service>` exists (a lost creation race with a concurrent run for another version is treated as success); if the mirror role lacks `ecr-public:CreateRepository`, it fails with an error naming the missing repo and the one-time manual creation command instead of half-copying. - **Post-copy verification**: resolves the destination and asserts its index digest equals the expected digest. - A `workflow_dispatch` trigger with equivalent inputs (`service`, `version`, `digest`) supports manual runs. Note that `repository_dispatch` only runs the workflow version on the default branch, so the dispatch path only becomes active after this merges — which is also why CI cannot exercise it pre-merge; see the post-merge verification below. ### Post-merge verification (manual, dispatch can't run pre-merge) 1. Read the digest of a published slim release, e.g. `regctl manifest head ghcr.io/supabase/cli/postgrest:v16.2` (currently `sha256:125019473bbb8c0c09d5a9e49da2656840f71f71fdb903096cac80f46aceaa7b`). 2. Manually run this workflow via `workflow_dispatch` with `service=postgrest`, `version=v16.2`, and that digest. 3. Confirm `regctl manifest head public.ecr.aws/supabase/cli/postgrest:v16.2` returns the same digest. 4. Re-run the same dispatch and confirm it exits successfully with the destination digest unchanged (the copy re-runs as a cheap incremental verification). Go-live order after merge: create the `cli/*` ECR Public repos manually if the role can't, set `CLI_MIRROR_DISPATCH_TOKEN` in slim-services, then trigger the slim-services backfill (`ECR mirror check` with `request: true`). ## Linked issue Internal task (Supabase maintainer, no `open-for-contribution` issue). - [x] The linked issue is **open** and carries the `open-for-contribution` label (or I'm a Supabase maintainer). ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/) (e.g. `fix(cli): …`). - [x] Tests added or updated for the change. (Workflow-only change: `actionlint` passes, and the validation script was exercised locally against good payloads, digest mismatches, bad service names, and out-of-namespace source/destination strings.) - [x] From the repository root, `pnpm check:all` passes; relevant package tests pass for every touched workspace, and `pnpm types:check` passes for each touched TypeScript workspace (or workspace declaring it). (No TypeScript workspace touched.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019vxDP5STtHeohcy727UrrR --------- Co-authored-by: Claude <noreply@anthropic.com>
<!-- Before opening this PR, confirm the linked issue is open and carries the `open-for-contribution` label. PRs from external contributors that do not follow the workflow in CONTRIBUTING.md are closed automatically. @supabase members working from Linear tickets are exempt. --> ## Summary Adds `SUPABASE_FUNCTION_SLUG` to every locally served Edge Function. The value always matches the requested function name. This works in both the legacy and next stacks. **Context** - `@supabase/server` uses this value in `withOAuthProtectedResource`. - See [supabase/server#117](supabase/server#117). **Shared function folders** - Edge Runtime reuses workers by their service path. - Two functions can share one source folder. They must not share one worker environment. - The CLI now gives each shared function a stable and unique worker path. - The CLI still passes the real source file as the entrypoint. Imports and file access remain unchanged. - Functions in separate folders keep their current service path. - The change does not use queues, owner maps, or `forceCreate`. ## Linked issue Fixes AI-1129 - [x] The linked issue is **open** and carries the `open-for-contribution` label, or I am a Supabase maintainer. ## Checklist - [x] The PR title follows [Conventional Commits](https://www.conventionalcommits.org/). - [x] Tests were added or updated for the change. - [ ] From the repository root, `pnpm check:all` passes, and all required workspace checks pass.
…hema (#6425) ## What kind of change does this PR introduce? Bug fix (CI). ## What is the current behavior? The `Codegen` job in the `CI` workflow runs `go generate` against the live Management API spec (`api.supabase.green`) and fails the build if the checked-in `pkg/api` files drift from what it produces. Upstream started splitting every response component schema into a base and `_Output` variant (e.g. `JitListAccessResponse` -> `JitListAccessResponse_Output`), which broke three `apps/cli-go/api/overlay.yaml` selectors targeting the old schema name: ``` failed to apply Overlay "api/overlay.yaml" ... selector "$.components.schemas.JitListAccessResponse.properties.items.items.anyOf[0].properties.invite_id" did not match any targets ``` This has failed the `Codegen` check on every `develop` commit since #6417 (merged 2026-09-01), blocking the merge queue for all PRs since the `merge_group` trigger has no path filter. ## What is the new behavior? - `overlay.yaml` selectors repointed at `JitListAccessResponse_Output` (schema shape is unchanged, only the name). - Regenerated `pkg/api/{types,client}.gen.go` against the current live spec, which also renames every other response schema type to its `*Output` counterpart. - Renamed all downstream Go references (`pkg/config`, `pkg/function`, `internal/utils`, `internal/telemetry`, `internal/functions/download`) to the new `*Output` type names so the module still builds. Verified: `go build ./...`, `go vet ./...`, `golangci-lint run`, and `go generate` (re-run to confirm idempotency) all pass in `apps/cli-go`. `go test ./...` in `apps/cli-go` is green aside from two pre-existing, environment-only failures (no local Docker daemon). `pkg/config`'s test suite has ~20 pre-existing failures that are identical on a clean `develop` checkout (confirmed via a baseline worktree) — unrelated to this change, and that submodule isn't part of the CI `Test` job's scope anyway. ## Related Issue(s) Unblocks the merge queue (e.g. #6423).
## What kind of change does this PR introduce? Feature — flips `packages/config` to `private: false`, activating the publish half of the release pipeline that landed in #6381, and drops the README's "not yet published" caveat. ## What is the current behavior? `@supabase/config` is `private: true`: every push touching `packages/config/**` rehearses the plan half of the Release Config workflow (version computation, build, pack, type-surface gate), but `should_release` stays false and nothing publishes. npm currently hosts only a `0.0.0` placeholder stub. ## What is the new behavior? Merging this PR is the package's first real release. The squash commit (`feat(config)`) is the first releasable commit since the `config-v0.0.0` baseline tag, so the Release Config workflow will: 1. plan **0.1.0** (minor over the 0.0.0 stub baseline), 2. pack the tarball and generate the approval evidence — since the stub contains no `.d.ts`, the type-surface gate renders the **entire public surface as additions** for the approver, 3. wait on `config-release` environment approval (required reviewers configured), 4. publish that exact tarball via OIDC trusted publishing, push `config-v0.1.0`, and create the GitHub release (never repo-"latest"). Go-live preconditions, all in place: npm trusted publisher configured and bootstrap token revoked (verified with infra/security), `config-release` environment armed with required reviewers, `config-v0.0.0` baseline tag pushed at ed81a1c and verified green (plan run reports "0 commits: no release" pre-merge). Part of CLI-2169.
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected in the generated API code after syncing with the latest spec from infrastructure. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>